package cn.cyh.imeans.utils;

import cn.cyh.imeans.entity.DeptTree;
import cn.cyh.imeans.entity.SysOrg;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class DeptThreeUtil {
    private DeptThreeUtil(){}

    /**
     * 机构数据
     * 保存各节点在树中的位置
     * **/
    private static final Map<String, List<Integer>> DEPT_INDEX_MAP = new HashMap<>(2<<16);
    /**
     * 初始化时构建的部门树结构
     * 提升查询树结构的速度 直接根据构件的索引从树结构中获取
     * **/
    private static final List<DeptTree> DEPT_TREE_LIST = new ArrayList<>(2);

    /**
     * 部门信息缓存
     */
    public static final Map<String, SysOrg> DEPART_MAP = new HashMap<>(16);
    /**pcode对应关系, dwdm-pcode**/
    public static final Map<String, String> DEPART_PCODE_MAP = new HashMap<>(16);
    public static final Map<String, SysOrg> DEPART_DWDM_MAP = new HashMap<>(16);


    /**
     * 构建组织机构树形结构
     * 提前构建，使用时直接从缓存中获取
     */
    public static void getAllTree(){
        List<DeptTree> tree = getAllDeptTree(DEPART_MAP);
        DEPT_INDEX_MAP.clear();
        DEPT_TREE_LIST.clear();
        for (int i = 0; i < tree.size(); i++) {
            DeptTree treeVO = tree.get(i);
            List<Integer> singleton = Collections.singletonList(i);
            DEPT_INDEX_MAP.put(treeVO.getValue(), new ArrayList<>(singleton));
            itertorTreeForIndex(treeVO.getChildren(), singleton);
        }
        DEPT_TREE_LIST.addAll(tree);
    }

    /**
     * 从部门树中获取子树
     * @param auth 是否认证，即只获取所在单位下的部门信息，而不是全部单位
     * @param deptId 部门id
     * @return list
     */
    private static List<DeptTree> getTreeNodeFromTree(Integer auth, String deptId) {
        List<DeptTree> l = new ArrayList<>(DEPT_TREE_LIST);
        if(auth != null && auth == 0) {
            return l;
        }
        List<Integer> list = DEPT_INDEX_MAP.get(deptId);
        if(list == null || list.size() == 0) {
            return new ArrayList<>(0);
        }
        DeptTree t = null;
        for (int index : list) {
            if(l == null || l.size() == 0) {
                break;
            }
            t = l.get(index);
            if (t != null) {
                l = t.getChildren();
            } else {
                break;
            }
        }
        List<DeptTree> li = new ArrayList<>(1);
        if(t != null) {
            li.add(t);
        }
        return li;
    }

    /**
     * 从部门树中获取子树
     * @param deptId 部门id
     * @return list
     */
    public static List<DeptTree> getTreeNodeFromTreeByPcode(Integer auth, String deptId) {
        String pcode = DEPART_PCODE_MAP.get(deptId);
        return getTreeNodeFromTree(auth, pcode != null && !"".equals(pcode) ? pcode : deptId);
    }

    /**
     * 获取所有子集的机构代码
     * @param deptId 组织机构代码
     * @return list
     */
    public static List<String> getTreeChildIds(String deptId){
        return getTreeChildIdsAuth(1, deptId, true);
    }

    /**
     * 获取子集对应的所有下级单位代码
     * @param deptId 查询的id
     * @return  map
     */
    public static Map<String, List<String>> getNextDeptId(String deptId) {
        SysOrg sysOrg = DEPART_MAP.get(deptId);
        Map<String, List<String>> map = new HashMap<>(16);
        List<String> li = new ArrayList<>(1);
        li.add(deptId);
        map.put(deptId, li);
        if(sysOrg == null) {
            return map;
        }
        if(!deptId.equals(sysOrg.getDwdm())) {
            List<String> li1 = new ArrayList<>(2);
            li1.add(deptId);
            li1.add(sysOrg.getDwdm());
            map.put(deptId, li1);
        }
        //获取所有的子编码
        Set<String> childSet = new HashSet<>(10);
        DEPART_MAP.forEach((key1, value1) -> {
            if (value1.getPcode() != null && !"".equals(value1.getPcode()) && value1.getPcode().equals(deptId)) {
                childSet.add(key1);
            }
        });
        for (String id : childSet) {
            map.put(id, getTreeChildIds(id));
        }
        return map;
    }

    /**
     * 获取组织结构-树结构
     * @return list
     */
    public static List<DeptTree> getAllDeptTree(Map<String, SysOrg> map) {
        List<DeptTree> list = new ArrayList<>(10);
        List<SysOrg> values = new ArrayList<>(map.values());
        values.forEach(value -> {
            if(value.getPcode() == null || "".equals(value.getPcode())) {
                DeptTree vo = new DeptTree();
                vo.setValue(value.getPcode());
                vo.setDwdm(value.getDwdm());
                vo.setLabel(value.getDwmc());
                list.add(vo);
            }
        });
        //找出下级
        itertorTree(list, values, "派出所");
        return list;
    }
    private static void itertorTree(List<DeptTree> list, List<SysOrg> values, String lastName) {
        for (DeptTree tree : list) {
            if(tree.getLabel() != null && !"".equals(tree.getLabel()) && tree.getLabel().contains(lastName)) {
                continue;
            }
            List<DeptTree> children = tree.getChildren();
            for (SysOrg value : values) {
                if (tree.getValue().equals(value.getPcode())) {
                    DeptTree vo = new DeptTree();
                    vo.setValue(value.getPcode());
                    vo.setDwdm(value.getDwdm());
                    vo.setLabel(value.getDwmc());
                    children.add(vo);
                }
            }
            tree.setChildren(children);
            if(children.size() > 0) {
                itertorTree(children, values, lastName);
            }
        }
    }

    /**
     * 获取子集单位编码
     * @param auth 有无权限
     * @param deptId 单位代码
     * @param needEmpty 是否允许顶级返回空集
     * @return list
     */
    private static List<String> getTreeChildIdsAuth(Integer auth, String deptId, boolean needEmpty){
        // 2022-03-25 通过pcode查询
        String pcode = DEPART_PCODE_MAP.get(deptId);
        boolean nullPcode = pcode != null && !"".equals(pcode);
        //如果pcode对应的数据为空，就返回空（査所有）
        SysOrg sysOrgZk = DEPART_DWDM_MAP.get(nullPcode ? pcode : deptId);
        if(sysOrgZk != null && (sysOrgZk.getPcode() == null || "".equals(sysOrgZk.getPcode())) && needEmpty) {
            return new ArrayList<>(0);
        }
        List<DeptTree> child = getTreeNodeFromTree(auth, nullPcode ? pcode : deptId);
        Set<String> set = new HashSet<>(10);
        itertorTreeChildId(child, set);
        return new ArrayList<>(set);
    }
    private static void itertorTreeChildId(List<DeptTree> child, Set<String> set) {
        if(child != null && child.size() > 0) {
            for (DeptTree tree : child) {
                set.add(tree.getDwdm());
                itertorTreeChildId(tree.getChildren(), set);
            }
        }
    }
    private static void itertorTreeForIndex(List<DeptTree> children, List<Integer> indexs) {
        if(children != null && children.size() > 0) {
            for (int i = 0; i < children.size(); i++) {
                DeptTree treeVO = children.get(i);
                List<Integer> indexs1 = new ArrayList<>(indexs);
                indexs1.add(i);
                DEPT_INDEX_MAP.put(treeVO.getValue(), indexs1);
                itertorTreeForIndex(treeVO.getChildren(), indexs1);
            }
        }
    }

}
